"""
Case Type   : 极致RTO-数据库系统类
Case Name   : gsc开关打开，极致RTO场景下，主备多次switchover，新主执行ddl，dml功能正常
Create At   : 2022/5/10
Owner       : opentestcase024
Description :
    1、设置极致RTO及GSC参数;
    2、重启数据库，使参数生效;
    3、主机进行ddl，dml;
    查询主备状态
    4、备机执行switchover;
    查询主备状态
    5、新主机对相同表进行ddl，dml;
    查询主备状态
    6、备机执行switchover;
    查询主备状态
    7、新主机对相同表进行ddl，dml;
    查询主备状态
Expect      :
    1、设置极致RTO及GSC参数; 成功
    2、重启数据库，使参数生效; 重启成功
    3、主机进行ddl，dml; 执行成功
    查询主备状态正常
    4、备机执行switchover; 执行成功
    查询主备状态正常
    5、新主机对相同表进行ddl，dml; 执行成功
    查询主备状态正常
    6、备机执行switchover; 执行成功
    查询主备状态正常
    7、新主机对相同表进行ddl，dml; 执行成功
    查询主备状态正常
History     :
    Modified by peilinqian at 2025/1/21:teardown增加集群主备恢复动作，以防对其他用例产生影响
"""
import os
import time
import unittest

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node

pri_sh = CommonSH('PrimaryDbUser')
node_num = pri_sh.get_node_num()


@unittest.skipIf(3 != node_num, '非1+2环境不执行')
class GscTestCase(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.log.info(f'----{os.path.basename(__file__)}:start----')
        self.log.info("----this is setup----")
        self.pri_root = Node(node='PrimaryRoot')
        self.pri_sh = CommonSH('PrimaryDbUser')
        self.sta_1_sh = CommonSH('Standby1DbUser')
        self.com = Common()
        self.constant = Constant()
        self.max_num = 10000
        self.table_test = 'tb_gsc0028'
        self.create_sql = f'''drop table if exists {self.table_test};
            create table {self.table_test}(id int);
            insert into {self.table_test} values 
            (generate_series(1,{self.max_num}));'''
        self.select_sql = f'select count(*) from {self.table_test};'
        self.drop_sql = f'drop table {self.table_test};'

    def test_main(self):
        step_txt = '----step0:查询参数初始值;----'
        self.log.info(step_txt)
        self.init_para1 = self.com.show_param('replication_type')
        self.init_para2 = self.com.show_param('recovery_parse_workers')
        self.init_para3 = self.com.show_param('recovery_redo_workers')
        self.init_para4 = self.com.show_param('hot_standby')
        self.init_para5 = self.com.show_param('enable_global_syscache')

        step_txt = '----step1:设置极致RTO及GSC参数; expect:成功----'
        self.log.info(step_txt)
        msg = self.pri_sh.execute_gsguc('set',
                                        self.constant.GSGUC_SUCCESS_MSG,
                                        'replication_type=1')
        self.assertTrue(msg, '执行失败:' + step_txt)
        msg = self.pri_sh.execute_gsguc('set',
                                        self.constant.GSGUC_SUCCESS_MSG,
                                        'recovery_parse_workers=4')
        self.assertTrue(msg, '执行失败:' + step_txt)
        msg = self.pri_sh.execute_gsguc('set',
                                        self.constant.GSGUC_SUCCESS_MSG,
                                        'recovery_redo_workers=4')
        self.assertTrue(msg, '执行失败:' + step_txt)
        msg = self.pri_sh.execute_gsguc('set',
                                        self.constant.GSGUC_SUCCESS_MSG,
                                        'hot_standby=off')
        self.assertTrue(msg, '执行失败:' + step_txt)
        msg = self.pri_sh.execute_gsguc('set',
                                        self.constant.GSGUC_SUCCESS_MSG,
                                        f"enable_global_syscache= on")
        self.assertTrue(msg, '执行失败:' + step_txt)

        step_txt = '----step2:重启数据库，使参数生效; expect:重启成功----'
        self.log.info(step_txt)
        stop_result = self.pri_sh.stop_db_cluster()
        start_result = self.pri_sh.start_db_cluster()
        self.assertTrue(stop_result, '执行失败:' + step_txt)
        self.assertTrue(start_result, '执行失败:' + step_txt)

        step_txt = '----step3:主机进行ddl，dml; expect:执行成功----'
        self.log.info(step_txt)
        create_result = self.pri_sh.execut_db_sql(self.create_sql)
        self.log.info(create_result)
        select_result = self.pri_sh.execut_db_sql(self.select_sql)
        self.log.info(select_result)
        self.assertIn(self.constant.TABLE_CREATE_SUCCESS, create_result,
                      '执行失败:' + step_txt)
        self.assertIn(self.constant.TABLE_DROP_SUCCESS, create_result,
                      '执行失败:' + step_txt)
        self.assertIn(str(self.max_num), select_result, '执行失败:' + step_txt)

        self.log.info('----查询主备状态----')
        status_result = self.pri_sh.get_db_cluster_status('status')
        self.assertTrue(status_result, '执行失败:' + step_txt)

        step_txt = '----step4:备机执行switchover; expect:执行成功----'
        self.log.info(step_txt)
        suc_msg = self.constant.SWITCH_SUCCESS_MSG
        switchover_result = self.sta_1_sh.execute_gsctl('switchover', suc_msg)
        self.assertTrue(switchover_result, '执行失败:' + step_txt)
        refresh_result = self.sta_1_sh.exec_refresh_conf()
        self.assertTrue(refresh_result, '执行失败:' + step_txt)
        self.log.info('----查询主备状态----')
        status_result = self.pri_sh.get_db_cluster_status('status')
        self.assertTrue(status_result, '执行失败:' + step_txt)

        step_txt = '----step5:新主机对相同表进行ddl，dml; expect:执行成功----'
        self.log.info(step_txt)
        create_result = self.sta_1_sh.execut_db_sql(self.create_sql)
        self.log.info(create_result)
        select_result = self.sta_1_sh.execut_db_sql(self.select_sql)
        self.log.info(select_result)
        self.assertIn(self.constant.TABLE_CREATE_SUCCESS, create_result,
                      '执行失败:' + step_txt)
        self.assertIn(self.constant.TABLE_DROP_SUCCESS, create_result,
                      '执行失败:' + step_txt)
        self.assertIn(str(self.max_num), select_result, '执行失败:' + step_txt)

        self.log.info('----查询主备状态----')
        status_result = self.pri_sh.get_db_cluster_status('status')
        self.assertTrue(status_result, '执行失败:' + step_txt)

        step_txt = '----step6:备机执行switchover; expect:执行成功----'
        self.log.info(step_txt)
        suc_msg = self.constant.SWITCH_SUCCESS_MSG
        switchover_result = self.pri_sh.execute_gsctl('switchover', suc_msg)
        self.assertTrue(switchover_result, '执行失败:' + step_txt)
        refresh_result = self.pri_sh.exec_refresh_conf()
        self.assertTrue(refresh_result, '执行失败:' + step_txt)
        self.log.info('----查询主备状态----')
        status_result = self.pri_sh.get_db_cluster_status('status')
        self.assertTrue(status_result, '执行失败:' + step_txt)

        step_txt = f'----step7:新主机对相同表进行ddl，dml; expect:执行成功----'
        self.log.info(step_txt)
        create_result = self.pri_sh.execut_db_sql(self.create_sql)
        self.log.info(create_result)
        select_result = self.pri_sh.execut_db_sql(self.select_sql)
        self.log.info(select_result)
        self.assertIn(self.constant.TABLE_CREATE_SUCCESS, create_result,
                      '执行失败:' + step_txt)
        self.assertIn(self.constant.TABLE_DROP_SUCCESS, create_result,
                      '执行失败:' + step_txt)
        self.assertIn(str(self.max_num), select_result, '执行失败:' + step_txt)

        self.log.info('----查询主备状态----')
        status_result = self.pri_sh.get_db_cluster_status('status')
        self.assertTrue(status_result, '执行失败:' + step_txt)

    def tearDown(self):
        step_txt = '----this is teardown----'
        self.log.info(step_txt)
        host_name = self.pri_root.sh('hostname').result()
        if self.pri_sh.check_whether_need_switch(host_name):
            self.log.info('----主备关系异常，进行恢复----')
            self.pri_sh.start_db_cluster()
            self.log.info('---进行主备切换---')
            suc_msg = self.constant.SWITCHOVER_SUCCESS_MSG
            switch_result = self.pri_sh.execute_gsctl('switchover', suc_msg)
            self.log.info(switch_result)
            refresh_result = self.pri_sh.exec_refresh_conf()
            self.log.info(refresh_result)

        step1_txt = '----清理测试表; expect:清理成功----'
        self.log.info(step1_txt)
        drop_result = self.pri_sh.execut_db_sql(self.drop_sql)
        self.log.info(drop_result)
        step2_txt = '----恢复参数为初始值并查询; expect:设置成功----'
        self.log.info(step2_txt)
        msg1 = self.pri_sh.execute_gsguc('set',
                                         self.constant.GSGUC_SUCCESS_MSG,
                                         f"replication_type="
                                         f"{self.init_para1}")
        msg2 = self.pri_sh.execute_gsguc('set',
                                         self.constant.GSGUC_SUCCESS_MSG,
                                         f"recovery_parse_workers="
                                         f"{self.init_para2}")
        msg3 = self.pri_sh.execute_gsguc('set',
                                         self.constant.GSGUC_SUCCESS_MSG,
                                         f"recovery_redo_workers="
                                         f"{self.init_para3}")
        msg4 = self.pri_sh.execute_gsguc('set',
                                         self.constant.GSGUC_SUCCESS_MSG,
                                         f"hot_standby={self.init_para4}")
        msg5 = self.pri_sh.execute_gsguc('set',
                                         self.constant.GSGUC_SUCCESS_MSG,
                                         f"enable_global_syscache="
                                         f"{self.init_para5}")
        step3_txt = '----重启数据库，使参数生效; expect:重启成功----'
        self.log.info(step3_txt)
        restart_result = self.pri_sh.restart_db_cluster()
        step4_txt = '----查询数据库状态; expect:状态正常----'
        self.log.info(step4_txt)
        status = pri_sh.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        p_status = status.splitlines()[-1].split('|')[0].split('6001')[-1]
        if 'Primary' in p_status and "cluster_state   : Normal" in status:
            self.log.info('---集群状态正常，无需恢复为初始状态---')
        else:
            recovery = pri_sh.exec_cm_ctl(mode='switchover',
                                          param='-a')
            self.log.info(recovery)
            time.sleep(10)
        status_result = pri_sh.get_db_cluster_status('status')

        self.log.info(f'----{os.path.basename(__file__)}:end----')
        self.assertIn(self.constant.TABLE_DROP_SUCCESS, drop_result,
                      '执行失败:' + step_txt + step1_txt)
        self.assertTrue(msg1, '执行失败:' + step_txt + step2_txt)
        self.assertTrue(msg2, '执行失败:' + step_txt + step2_txt)
        self.assertTrue(msg3, '执行失败:' + step_txt + step2_txt)
        self.assertTrue(msg4, '执行失败:' + step_txt + step2_txt)
        self.assertTrue(msg5, '执行失败:' + step_txt + step2_txt)
        self.assertTrue(restart_result, '执行失败:' + step_txt + step3_txt)
        self.assertTrue(status_result, '执行失败:' + step_txt + step4_txt)
